package com.frank.im.base;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ServerHandshake;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v4.content.LocalBroadcastManager;

import com.frank.http.encryp.EncrypUtils;
import com.frank.http.expand.PreferenceAppService;
import com.frank.im.bean.ImRespData;
import com.frank.im.bean.ImRespStatusData;
import com.frank.im.db.ImDBManage;
import com.frank.im.db.ImDaoImpl;
import com.frank.im.utils.ImDataUtils;
import com.frank.im.utils.Logger;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

/**
 * im服务
 * 
 * @author Frank
 * @version 1.0 Create by 2016.4.8
 */
public class ImService extends Service implements Imable, ImConnExpable {
	private final static String TAG = ImService.class.getSimpleName();
	private final static int TIMING_CONNECT = 25;
	private final IBinder mBinder = new ImLocalBinder();
	private String wsUrl = "";
	private ImClient imClient = null;
	private Context context;
	private Map<String, ImCallback> callBackHashMap = new HashMap<String, ImCallback>();
	private Map<String, String> typeHashMap = new HashMap<String, String>();
	private Map<String, String> operateHashMap = new HashMap<String, String>();
	private boolean isLogin = false;
	private ImBroadcast imBroadcast = new ImBroadcast();
	private String tests; 

	private Handler mHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case TIMING_CONNECT:
				timingConnect();
				break;

			default:
				break;
			}
		}

	};

	private Handler handler = new Handler();
	private Runnable runnable = new Runnable() {

		@Override
		public void run() {
			Logger.i(TAG, "run_time");
			Message msg = Message.obtain();
			msg.what = TIMING_CONNECT;
			mHandler.sendMessage(msg);
			Logger.i(TAG, "run_time_stop");
			try {
				handler.postDelayed(this, 5000);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	};

	@Override
	public void onCreate() {
		super.onCreate();
		context = this;
		isLogin = false;
		ImDaoImpl.getInstance().onInit(context);
		registerImReceiver();
		handler.postDelayed(runnable, 1000); // 每隔5s执行
	}

	/**
	 * 定时链接
	 */
	private synchronized void timingConnect() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				Logger.i(TAG, "time_connect_run");
				if (imClient == null) {
					Logger.i(TAG, "imClient==null");
				} else {
					Logger.i(TAG, "imClient!=null");
					Logger.i(TAG, "open:" + Boolean.toString(imClient.isOpen()));
				}
				if (imClient != null && !imClient.isOpen()) {
					try {
						imClient = null;
						System.gc();
					} catch (Exception e) {
						e.printStackTrace();
					}

					try {
						wsUrl = PreferenceAppService.getInstance().getItem(
								"wsUrl");
						Logger.i(TAG, "time_connect地址：" + wsUrl);
						imClient = new ImClient(new URI(wsUrl));
						imClient.setImable(ImService.this);
					} catch (URISyntaxException e) {
						e.printStackTrace();
					} catch (Exception e) {
						e.printStackTrace();
					}
					Logger.i(
							TAG,
							"time_connect_start:"
									+ Boolean.toString(imClient.isOpen()));
					try {
						imClient.connectBlocking();
					} catch (Exception e) {
						e.printStackTrace();
						Logger.i(TAG, "time_connect_exception");
					}
					Logger.i(
							TAG,
							"time_connect_stop:"
									+ Boolean.toString(imClient.isOpen()));
					doReLogin(imClient.isOpen());
				}
				if (imClient == null) {
					try {
						wsUrl = PreferenceAppService.getInstance().getItem(
								"wsUrl");
						Logger.i(TAG, "time_connect地址：" + wsUrl);
						imClient = new ImClient(new URI(wsUrl));
						imClient.setImable(ImService.this);
					} catch (URISyntaxException e) {
						e.printStackTrace();
					} catch (Exception e) {
						e.printStackTrace();
					}
					Logger.i(
							TAG,
							"time_connect_start:"
									+ Boolean.toString(imClient.isOpen()));
					try {
						imClient.connectBlocking();
					} catch (Exception e) {
						e.printStackTrace();
						Logger.i(TAG, "time_connect_exception");
					}
					Logger.i(
							TAG,
							"time_connect_stop:"
									+ Boolean.toString(imClient.isOpen()));
					doReLogin(imClient.isOpen());
				}
			}
		}).start();

	}

	/**
	 * 断线重新登陆
	 * 
	 * @param isCommon
	 */
	public void doReLogin(boolean isCommon) {
		String loginState = PreferenceAppService.getInstance().getItem(
				"socketIsLogin");
		if (isCommon == true && !loginState.equals("0")
				&& Boolean.valueOf(loginState) == true) {
			login(EncrypUtils.getUUId(), new ImCallback() {

				@Override
				public void onStart() {

				}

				@Override
				public void onSuccess(String content) {
					Logger.i(TAG, "onSuccess login content:" + content);
					// ImDaoImpl.getInstance().onInit(context);
				}

				@Override
				public void onFailure(String content) {
					Logger.i(TAG, "onFailure content:" + content);
				}

			});
		}
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return mBinder;
	}

	/**
	 * 自定义绑定Service类，通过这里的getService得到Service，之后就可调用Service这里的方法了
	 */
	public class ImLocalBinder extends Binder {
		public ImService getService() {
			return ImService.this;
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (!imClient.isClosed()) {
			imClient.close();
			imClient = null;
		}
		unregisterImReceiver();
		ImDaoImpl.getInstance().closeDB();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return START_STICKY;
	}

	@Override
	public void onOpen(ServerHandshake handshakedata) {
		Logger.i(TAG, "onOpen");
	}

	@Override
	public void onMessage(String message) {
		Logger.i(TAG, "onMessage:" + message);
		Gson respGson = null;
		ImRespData respData = null;
		try {
			respGson = new Gson();
			respData = respGson.fromJson(message, new TypeToken<ImRespData>() {
			}.getType());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {

		}
		if (respData != null) {
			allResponse(respData, message);
		}
	}

	/**
	 * 所有响应处理
	 * 
	 * @param respData
	 * @param message
	 */
	public synchronized void allResponse(ImRespData respData, String message) {
		ImRespStatusData<?> imRespStatusData = null;
		Gson respGson = new Gson();
		String respStatusDataStr = "";
		if (respData != null) {
			respStatusDataStr = respData.data;
			Logger.i(TAG, "respStatusDataStr：" + respStatusDataStr);
			String operateType = "";
			if (operateHashMap != null) {
				operateType = operateHashMap.get(respData.request_id);
			}
			if (operateType != null && !operateType.equals("")) {
				if (operateType.equals("login")) {
					try {
						if (respStatusDataStr != null
								&& !respStatusDataStr.equals("")) {
							imRespStatusData = respGson.fromJson(
									respStatusDataStr,
									new TypeToken<ImRespStatusData<?>>() {
									}.getType());
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
					if (imRespStatusData != null && imRespStatusData.state
							&& imRespStatusData.code == 200) {
						PreferenceAppService.getInstance().setItem(
								"socketIsLogin", "true");
						isLogin = true;
						ImDaoImpl.getInstance().onInit(context);
						if (!ImDaoImpl.getInstance().isExists(
								1,
								String.valueOf(ImChatManage.getInstance()
										.getAppMarkUtil().getUserId()))) {
							/*** 获取用户信息 ***/
							ImDBManage.getInstance().getUserInfo(
									context,
									Integer.parseInt(ImChatManage.getInstance()
											.getAppMarkUtil().getUserId()));
						}
					}
					loginOrLogoutResponse(respData, message, "login");
					operateHashMap.remove(respData.request_id);
				} else if (operateType.equals("logout")) {
					loginOrLogoutResponse(respData, message, "logout");
					operateHashMap.remove(respData.request_id);
				}
			} else {
				if (callBackHashMap != null) {
					ImCallback callback = callBackHashMap
							.get(respData.request_id);
					if (callback != null) {
						Logger.i(TAG, callback.toString());
						callback.onSuccess(message);
						callBackHashMap.remove(respData.request_id);
					}
				}
				if (respData.path.equals("")) {
					String type = "";
					if (typeHashMap != null) {
						type = typeHashMap.get(respData.request_id);
						if (type != null) {
							typeHashMap.remove(respData.request_id);
						} else {
							type = "";
						}
					}
					respMessage(type, respData);
				} else {
					pushMessage(respData);
				}
			}
		}
	}

	/**
	 * 推送
	 */
	public synchronized void pushMessage(ImRespData respData) {
		switch (respData.path) {
		case "un_read_msg":
			ImDBManage.getInstance().dealMsgCont(context, respData);
			sendImBroadcast(ImBroadcast.RESP_TYPE_PUSH,
					ImBroadcast.OPERATE_TYPE_UN_READMSG, respData);
			break;
		case "receive_msg":
			ImDBManage.getInstance().dealMsgCont(context, respData);
			sendImBroadcast(ImBroadcast.RESP_TYPE_PUSH,
					ImBroadcast.OPERATE_TYPE_RECEIVE_MSG, respData);
			break;
		case "un_read_sys_msg":
			ImDBManage.getInstance().dealSysMsg(context, respData);
			sendImBroadcast(ImBroadcast.RESP_TYPE_PUSH,
					ImBroadcast.OPERATE_TYPE_UN_READ_SYS_MSG, respData);
			break;
		case "new_sys_msg":
			ImDBManage.getInstance().dealSysMsg(context, respData);
			sendImBroadcast(ImBroadcast.RESP_TYPE_PUSH,
					ImBroadcast.OPERATE_TYPE_NEW_SYS_MSG, respData);
			break;

		default:
			break;
		}

	}

	public void sendImBroadcast(String respType, String operateType,
			ImRespData respData) {
		Logger.i(TAG, "开始发送广播");
		Intent intent = new Intent();
		intent.setAction("com.fank.ImBroadcastReceiver");
		intent.putExtra("respType", respType);
		intent.putExtra("operateType", operateType);
		if (respData != null) {
			intent.putExtra("data", respData);
		}
		LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

		Intent notifyIntent = new Intent();
		notifyIntent.setAction("com.frank.notify");
		if (respData != null) {
			notifyIntent.putExtra("type", "show");
			notifyIntent.putExtra("data", respData);
		}
		context.sendBroadcast(notifyIntent);

	}

	/**
	 * 发送响应
	 */
	public synchronized void respMessage(String type, final ImRespData respData) {
		switch (type) {
		case ImConstant.SEND_TO_ONE:
			ImDBManage.getInstance().dealSendResp(context, respData);
			sendImBroadcast(ImBroadcast.RESP_TYPE_RESP,
					ImBroadcast.OPERATE_TYPE_SEND_FINISHED, respData);
			// new Thread(new Runnable() {
			//
			// @Override
			// public void run() {
			// try {
			// Thread.sleep(1000);
			// } catch (InterruptedException e) {
			// // TODO Auto-generated catch block
			// e.printStackTrace();
			// }
			// }
			// }).start();
			break;
		case ImConstant.MARK_AS_READ:
			// sendImBroadcast(ImBroadcastReceiver.RESP_TYPE_RESP,
			// ImBroadcastReceiver.OPERATE_TYPE_SEND_FINISHED, respData);
			break;
		case ImConstant.MARK_AS_SYS_READ:
			// sendImBroadcast(ImBroadcastReceiver.RESP_TYPE_RESP,
			// ImBroadcastReceiver.OPERATE_TYPE_SEND_FINISHED, respData);
			break;
		case ImConstant.GET_USER_INFO:
			sendImBroadcast(ImBroadcast.RESP_TYPE_RESP,
					ImBroadcast.OPERATE_TYPE_GET_USER_FINISHED, respData);
			break;

		default:
			break;
		}
	}

	/**
	 * 登陆或注销的响应处理
	 * 
	 * @param respData
	 */
	public void loginOrLogoutResponse(ImRespData respData, String message,
			String type) {
		Logger.i(TAG, "respData.request_id:" + respData.request_id);

		if (callBackHashMap != null) {
			ImCallback callback = callBackHashMap.get(respData.request_id);
			if (callback != null) {
				Logger.i(TAG, callback.toString());
				callback.onSuccess(message);
				callBackHashMap.remove(respData.request_id);
			}
		}
	}

	@Override
	public void onFragment(Framedata fragment) {
		Logger.i(TAG, "onFragment");
	}

	@Override
	public void onClose(int code, String reason, boolean remote) {
		Logger.i(TAG, "onClose");
		if (callBackHashMap != null && callBackHashMap.size() > 0) {
			ImDBManage.getInstance().dealSendFailed();
			sendImBroadcast(ImBroadcast.RESP_TYPE_RESP,
					ImBroadcast.OPERATE_TYPE_SEND_FAILED, null);
		}
	}

	@Override
	public void onError(Exception ex) {
		Logger.i(TAG, "onError");
		ex.printStackTrace();
		if (callBackHashMap != null && callBackHashMap.size() > 0) {
			ImDBManage.getInstance().dealSendFailed();
			sendImBroadcast(ImBroadcast.RESP_TYPE_RESP,
					ImBroadcast.OPERATE_TYPE_SEND_FAILED, null);
		}
	}

	@Override
	public synchronized void login(String requestId, ImCallback callback) {
		Logger.i(TAG, "requestId:" + requestId);
		if (operateHashMap != null) {
			operateHashMap.put(requestId, "login");
		}
		if (callBackHashMap != null && callback != null) {
			callBackHashMap.put(requestId, callback);
		}
		send(requestId, "", ImDataUtils.getInitData(context, requestId));
	}

	@Override
	public synchronized void logout(String requestId, ImCallback callback) {
		PreferenceAppService.getInstance().setItem("socketIsLogin", "false");
		isLogin = false;
		try {
//			ImDaoImpl.getInstance().closeDB();
			if (!imClient.isClosed()) {
				imClient.close();
				imClient = null;
			}
			System.gc();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public synchronized void send(String requestId, String type,
			String content, ImCallback callback) {
		if (callBackHashMap != null && callback != null) {
			callBackHashMap.put(requestId, callback);
		}
		if (typeHashMap != null) {
			typeHashMap.put(requestId, type);
		}

		String reqContent = ImDataUtils.getSendContent(context, requestId,
				type, content);
		if (type.equals(ImConstant.SEND_TO_ONE)) {
			Logger.i(TAG, "send_to_one");
			ImDBManage.getInstance().sendMsg(context, reqContent);
			callback.onStart();
			sendImBroadcast(ImBroadcast.RESP_TYPE_RESP,
					ImBroadcast.OPERATE_TYPE_SEND_START, null);
		}

		send(requestId, type, reqContent);
	}

	public synchronized void send(String requestId, String type,
			final String content) {
		Logger.i(TAG, "即将发送：" + content);

		if (imClient != null) {
			new Thread(new Runnable() {

				@Override
				public void run() {
					try {
						while (!imClient.isOpen()) {
							Logger.i(
									TAG,
									"send_open_start:"
											+ Boolean.toString(imClient
													.isOpen()));
							try {
								imClient.connectBlocking();
							} catch (Exception e) {
								e.printStackTrace();
							}
							Thread.sleep(5000);
							Logger.i(
									TAG,
									"send_open:"
											+ Boolean.toString(imClient
													.isOpen()));
						}
						Logger.i(TAG, "开始发送：" + content);
						imClient.send(content);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}).start();
		}
	}

	@Override
	public synchronized boolean isConn() {
		if (imClient != null && imClient.isOpen()) {
			return true;
		}
		return false;
	}

	@Override
	public synchronized boolean isLogin() {
		if (imClient != null && imClient.isOpen() && isLogin) {
			return true;
		}
		return false;
	}

	/**
	 * 注册通讯广播
	 */
	public void registerImReceiver() {
		if (imBroadcast != null) {
			IntentFilter filter = new IntentFilter();
			filter.addAction("com.fank.ImBroadcastReceiver");
			LocalBroadcastManager.getInstance(this).registerReceiver(
					imBroadcast, filter);
		}
	}

	/**
	 * 解绑通讯广播
	 */
	public void unregisterImReceiver() {
		if (imBroadcast != null) {
			LocalBroadcastManager.getInstance(this).unregisterReceiver(
					imBroadcast);
		}
	}
}
